package com.smforj.ssm.modules.eslib.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.smforj.ssm.modules.eslib.dao.CirculationDao;
import com.smforj.ssm.modules.eslib.dao.CirculationLogDao;
import com.smforj.ssm.modules.eslib.dao.ReaderDao;
import com.smforj.ssm.modules.eslib.domain.BookExtends;
import com.smforj.ssm.modules.eslib.domain.Circulation;
import com.smforj.ssm.modules.eslib.domain.CirculationLog;
import com.smforj.ssm.modules.eslib.domain.Reader;
import com.smforj.ssm.modules.eslib.domain.ReaderVo;
import com.smforj.ssm.modules.eslib.domain.vo.LibBookVo;
import com.smforj.ssm.modules.lib.dao.EditingLogDao;
import com.smforj.ssm.modules.lib.dao.LibBookDao;
import com.smforj.ssm.modules.lib.dao.SysBookinfoDao;
import com.smforj.ssm.modules.lib.dao.SysReaderDao;
import com.smforj.ssm.modules.lib.domain.CheckInResponse;
import com.smforj.ssm.modules.lib.domain.CheckOutResponse;
import com.smforj.ssm.modules.lib.domain.EditingLog;
import com.smforj.ssm.modules.lib.domain.EditingRequest;
import com.smforj.ssm.modules.lib.domain.FeePaidResponse;
import com.smforj.ssm.modules.lib.domain.ItemResponse;
import com.smforj.ssm.modules.lib.domain.LibraryRequest;
import com.smforj.ssm.modules.lib.domain.PatronResponse;
import com.smforj.ssm.modules.lib.domain.RFIDRequest;
import com.smforj.ssm.modules.lib.domain.SysBook;
import com.smforj.ssm.modules.lib.domain.SysReader;
import com.smforj.ssm.modules.lib.domain.Tag;
import com.smforj.ssm.modules.lib.domain.vo.SysBookVo;
import com.smforj.ssm.modules.lib.service.LibraryService;
import com.smforj.ssm.modules.sys.domain.SysUser;
import com.smforj.ssm.modules.sys.util.FatherToChildUtils;
import com.smforj.ssm.util.DateFormat;

/***
 * 图书管理系统接口实现类,该接口实现了图书馆员产品所有接口
 * 
 * 
 * service层进行事务处理，当出现错误时事务进行回滚
 *
 * @author Haijun Gao 
 * @date 2016-8-6 上午11:20:43
 * @desp http://www.cnblogs.com/saga5998/
 * @email 573107773@qq.com
 */
@Service("eslibraryService") 
public class EsLibraryServiceImpl implements LibraryService {
    private static final Log ESERVICELOG = LogFactory.getLog(EsLibraryServiceImpl.class);

    /***
     * 图书管理软件读者信息
     */
    @Autowired
    private ReaderDao readerDao; 
    
    /****
     * 本地数据访问对象
     */
    @Autowired
    private SysReaderDao sysReaderDao;
    /***
     * 借阅信息表
     */  
    @Autowired
    private CirculationDao circulationDao;
    @Autowired
    private CirculationLogDao circulationLogDao;
    
    @Autowired
    private EditingLogDao editingLogDao;

    /***
     * 图书管理软件Service
     */
    @Autowired
    private LibBookDao bookDao;
    /****
     * 本地库对象
     */
    @Autowired
    private SysBookinfoDao sysBookDao; 

    /***
     * 登陆 图书管理系统
     * @param request 请求信息 包含图书信息，读者信息
     * @return 成功 message 为 User 失败 message 为 error message
     * @date 2016-8-3 下午2:24:56
     */
    @Override
    public PatronResponse getReader(LibraryRequest<String> request) {
        Reader query = new Reader();
        query.setJszh(request.getSzUserId());
        PatronResponse patron = new PatronResponse();
        try {
            ReaderVo rv = readerDao.selectOne(query);
            patron.setStatus(1);
            patron.setReaderName(rv.getDzmc());
            patron.setHoldItemsCount(rv.getYjs().toString());
            patron.setFeeMax(Double.parseDouble(rv.getYqfk()));
            //有未交的罚金
            List<CirculationLog> listLog = circulationLogDao.selectCirculationLogByJsrbh(rv.getJszh());
            if (listLog != null) {
                patron.setFine(Double.parseDouble(rv.getYqfk()) * listLog.size());
            }
            patron.setReaderFee(0.0);
            //有超期图书
            List<Circulation> list = circulationDao.getCirculations(rv.getJszh());
            if (list != null && list.size() > 0) {
                String[] holdBooks = new String[list.size()];
                List<String> overdueBooks = new ArrayList<String>();
                for (int i = 0; i < list.size(); i++) {
                    holdBooks[i] = list.get(i).getSm() + "|" + list.get(i).getYhrq();
                    //超期
                    if (DateFormat.stringToDate(list.get(i).getYhrq()).getTime() > new Date().getTime()) {
                        overdueBooks.add(list.get(i).getSm() + "|" + list.get(i).getYhrq());
                    }
                }
                if (overdueBooks.size() > 0)
                    patron.setOverdueBooks(overdueBooks.toArray(new String[overdueBooks.size()]));
                patron.setHoldBooks(holdBooks);
            }

        } catch (Exception ex) {
            ESERVICELOG.error("查询读者信息异常：" + ex.getMessage());
            patron.setStatus(0);
            patron.setMessage("查询读者信息异常");
        }
        return patron;
    }

    /***
     * 查询多本图书信息
     * @param request 请求信息 包含图书id或Barcode
     * @return 成功 message 为 图书信息 失败 message 为 error message
     * @date 2016-11-1 下午3:22:27
     */
    @Override
    public ItemResponse getBookInfo(LibraryRequest<String> request) {
        ItemResponse item = new ItemResponse();
        try {
        	LibBookVo book = bookDao.getBookBytstm(request.getData());
            if (book != null) {
                item.setStatus(1);
                item.setBookId(book.getTsbh());
                //流通使用
                item.setBarcode(book.getTstm());
                item.setBookName(book.getZtm());
                item.setCallNum(book.getSsh());
            } else {
                item.setStatus(0);
                item.setMessage("无该图书");
            }
        } catch (Exception ex) {
            ESERVICELOG.error("查询图书信息异常：" + ex.getMessage());
            item.setStatus(0);
            item.setMessage("查询异常");
        }
        return item;
    }


    /***
     * 借阅图书
     * @param request 请求信息 包含图书信息，读者信息
     *   必须字段 readerid,bookid
     *   可行字段 pwd
     * @return 成功 message 为 更新后的book 失败 message 为 error message
     * @date 2016-8-3 下午3:01:16
     */
    @Override
    public List<CheckOutResponse> doCheckout(LibraryRequest<String[]> request) {
        List<CheckOutResponse> list = new ArrayList<CheckOutResponse>();
        for (String sbook : request.getData()) {
            CheckOutResponse iRes = null; 
        	LibBookVo book = bookDao.getBookBytstm(sbook);
            Reader reader = readerDao.selectById(request.getSzUserId());
            if (book != null && reader != null) {
                BookExtends be = bookDao.getBookExtends(book.getFlh().substring(0, 1), reader.getDzlx());
                if (be != null) {
                    //book.setId(sbook.getRfid());
                    book.setYhrq(getDate(new Date(), be.getKjts()));

                    iRes = checkOut(book, reader);
                    list.add(iRes);
                } else {
                    iRes = new CheckOutResponse();
                    iRes.setStatus(0);
                    iRes.setMessage("图书信息不正确，缺少从表信息");
                    list.add(iRes);
                }
            } else {
                iRes = new CheckOutResponse();
                iRes.setStatus(0);
                iRes.setMessage("图书信息或读者不正确");
                list.add(iRes);
            } 
        }
        return list;
    }

    /***
     * 私有方法 借阅功能业务方法
     * @param book 图书信息（图书管理软件中的图书）
     * @param reader 读者信息
     * @return
     * @date 2018年5月21日 上午10:58:30
     */
    private CheckOutResponse checkOut(LibBookVo book, Reader reader) {
        CheckOutResponse cor = new CheckOutResponse();
        cor.setRfid(book.getId());
        cor.setBookId(book.getId());
        cor.setBookName(book.getZtm());
        cor.setBarcode(book.getTstm());
        cor.setOccurDate(DateFormat.dateToString(DateFormat.FORMATDATE));
        try {
            //判断是否已经借阅
            Circulation cir = circulationDao.getCirculationBytsm(book.getTstm());
            //未借阅
            if (cir == null) {
                cir = getCirculation(book, reader);
                int iRes = circulationDao.insertCirculation(cir);
                if (iRes > 0) {
                    cor.setStatus(1);
                    cor.setMessage("借阅成功");
                    cor.setNeedReturnDate(cir.getYhrq());
                    cor.setOccurDate(cir.getJsrq());
                } else {
                    cor.setStatus(0);
                    cor.setMessage("借阅失败");
                }

            } else {
                cor.setNeedReturnDate(cir.getYhrq());
                cor.setOccurDate(cir.getJsrq());
                cor.setStatus(0);
                cor.setMessage("图书已经借阅");
            }

        } catch (Exception ex) {
            ESERVICELOG.error("checkOut", ex);
            cor.setStatus(0);
            cor.setMessage("借阅异常");
        }
        return cor;
    }

    /***
     * 创建借阅记录信息
     * @param book 图书信息
     * @param reader 读者信息
     * @return
     * @date 2018年6月10日 下午3:18:52
     */
    private Circulation getCirculation(LibBookVo book, Reader reader) {
        Date date = new Date();
        Circulation cir = new Circulation();
        cir.setTsm(book.getTstm());
        cir.setZch(book.getZch());
        cir.setFlh(book.getFlh());
        cir.setSm(book.getZtm());
        cir.setJsrq(DateFormat.dateToString(date, DateFormat.FORMATDATE));
        cir.setYhrq(DateFormat.dateToString(book.getYhrq(), DateFormat.FORMATDATE));
        cir.setGcd(book.getGcd());
        cir.setHsrq(null);
        cir.setXj(0);
        cir.setJsrbh(reader.getJszh()); 
        cir.setCzy("Terminal");
        cir.setZchfz(book.getZchfz());
        cir.setLx("");
        
        return cir;
    }

    /***
     * 获取日期
     * @param date 添加或减少天数
     * @return
     * @date 2017-7-5 下午4:23:21
     */
    public Date getDate(Date d, int date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(d);
        calendar.add(Calendar.DATE, 10);//把日期往后增加一天.整数往后推,负数往前移动
        return calendar.getTime();
    }

    /***
     * 归还图书
     * @param request 请求信息 包含图书信息，读者信息
     * @return 成功 message 为 更新后的book 失败 message 为 error message
     * @date 2016-8-3 下午3:01:16
     */
    @Override
    public List<CheckInResponse> doCheckin(LibraryRequest<String[]> request) {
        List<CheckInResponse> list = new ArrayList<CheckInResponse>();
        try {
            for (String sbook : request.getData()) {
            	LibBookVo book = bookDao.getBookBytstm(sbook);
                if (book != null) {
                    //book.setId(sbook.getRfid());
                    CheckInResponse iRes = checkIn(book);
                    list.add(iRes);
                }
            }
        } catch (Exception ex) {
            ESERVICELOG.error("还书失败: " + ex.getMessage());
        }
        return list;
    }

    private CheckInResponse checkIn(LibBookVo book) {
        CheckInResponse response = new CheckInResponse();
        response.setRfid(book.getId());
        response.setBookId(book.getId());
        response.setBookName(book.getZtm());
        response.setBarcode(book.getTstm());
        response.setOccurDate(DateFormat.dateToString(DateFormat.FORMATDATE));
        try {
            Circulation cir = circulationDao.getCirculationBytsm(book.getTstm());
            if (cir != null) {
                int iRes = circulationDao.deleteCirculation(cir);
                if (iRes > 0) {
                    CirculationLog cirLog = new CirculationLog();
                    FatherToChildUtils.fatherToChild(cir, cirLog);
                    cirLog.setHsrq(DateFormat.dateToString(DateFormat.FORMATDATE));
                    cirLog.setFj(0.00);
                    circulationLogDao.insertCirculationLog(cirLog);
                }
                response.setStatus(1);
                response.setMessage("还书成功");
            } else {
                response.setStatus(0);
                response.setMessage("还书失败");
            }
        } catch (Exception t) {
            ESERVICELOG.error("还书失败", t);
            response.setStatus(0);
            response.setMessage("还书失败");
        }
        return response;
    }

    /***
     * 续借图书
     * @param request 请求信息 包含图书信息，读者信息
     * @return 成功 message 为 更新后的book 失败 message 为 error message
     * @date 2016-8-3 下午3:01:16
     */
    @Override
    public List<CheckOutResponse> doRenew(LibraryRequest<String[]> request) {
        List<CheckOutResponse> list = new ArrayList<CheckOutResponse>(); 
        for (String sbook : request.getData()) {
            CheckOutResponse iRes = null;
            LibBookVo book = bookDao.getBookBytstm(sbook);
            Reader reader = readerDao.selectById(request.getSzUserId());
            if (book != null && reader != null) {
                BookExtends be = bookDao.getBookExtends(book.getFlh().substring(0, 1), reader.getDzlx());
                if (be != null) {
                    //book.setId(sbook.getRfid());
                    book.setYhrq(getDate(new Date(), be.getKxjsj()));
                    iRes = reNew(book, request.getSzUserId());
                    list.add(iRes);
                } else {
                    iRes = new CheckOutResponse();
                    iRes.setStatus(0);
                    iRes.setMessage("图书1信息不正确1");
                    list.add(iRes);
                }
            } else {
                iRes = new CheckOutResponse();
                iRes.setStatus(0);
                iRes.setMessage("2图书信息不正确2");
                list.add(iRes);
            }
        } 
        return list;
    }

    private CheckOutResponse reNew(LibBookVo book, String readerId) {
        CheckOutResponse cor = new CheckOutResponse();
        cor.setRfid(book.getId());
        cor.setBookId(book.getId());
        cor.setBookName(book.getZtm());
        cor.setBarcode(book.getTstm());
        cor.setOccurDate(DateFormat.dateToString(DateFormat.FORMATDATE));
        cor.setNeedReturnDate(DateFormat.dateToString(DateFormat.FORMATDATE));
        try {
            Circulation cir = circulationDao.getCirculation(book.getTstm(), readerId);
            if (cir != null) {
                cir.setXj(cir.getXj() + 1);
                //String date = cir.getYhrq();
                //System.out.println("------------"+date);
                //System.out.println("------------"+getRenewDate(date, 10));
                cir.setYhrq(DateFormat.dateToString(book.getYhrq(), DateFormat.FORMATDATE));
                cir.setJsrq(DateFormat.dateToString(DateFormat.FORMATDATE));
                int iRes = circulationDao.updateCirculation(cir);
                if (iRes > 0) {
                    cor.setStatus(1);
                    cor.setMessage("续借成功");
                    cor.setNeedReturnDate(cir.getYhrq());
                    cor.setOccurDate(cir.getJsrq());
                } else {
                    cor.setStatus(0);
                    cor.setMessage("续借失败");
                }
            } else {
                cor.setStatus(0);
                cor.setMessage("图书未借阅");
            }

        } catch (Exception ex) {
            ESERVICELOG.error("checkOut", ex);
            cor.setStatus(0);
            cor.setMessage("续借异常");
        }
        return cor;
    }

    /***
     * 登陆 图书管理系统
     * @param request 请求信息 读者信息
     * @return 成功 message 为 User 失败 message 为 error message
     * @date 2016-8-3 下午2:24:56
     */
    @Override
    public PatronResponse doLogin(LibraryRequest<String> request) {
        return getReader(request);
    }

    /****
     * 检测网络信息,方法使用了Exception不进行事务回滚
     */
    @Override
    public String testStatus(String id) {
        StringBuffer sb = new StringBuffer();
        sb.append(String.format("访问 API %s 正常; ", id)); 
        sb.append(" 访问 DB");
        long startTime = System.currentTimeMillis(); //获取当前时间
        System.out.print("begin：" + startTime); 
        sysReaderDao.selectCount();
        long endTime = System.currentTimeMillis();
        System.out.print("程序运行时间：" + (endTime - startTime) + "ms");
        sb.append(" 正常  ;");  
        sb.append("访问 LIB");
        readerDao.selectCount();
        sb.append(" 正常  ;");  
        return sb.toString();
    }

    @Override
    public List<ItemResponse> checkBookStatus(LibraryRequest<String[]> request) {
        List<ItemResponse> list = new ArrayList<ItemResponse>();
        try {
            for (String tsm : request.getData()) {
                ItemResponse item = new ItemResponse(); 
                item.setBarcode(tsm);
                Circulation circulation = circulationDao.getCirculationBytsm(tsm);
                //没有借阅报警
                if (circulation == null)
                    item.setStatus(1);
                else
                    item.setStatus(0);
                if (ESERVICELOG.isDebugEnabled())
                    ESERVICELOG.debug("checkBookStatus circulation " + tsm + "    " + (circulation == null ? "1" : "0"));
                list.add(item);
            }
        } catch (Exception ex) {
            ESERVICELOG.error(" checkBookStatus 异常： " + ex.getCause().getMessage());
        }
        return list;
    }

    @Override
    public FeePaidResponse doPayFee(LibraryRequest<String> request) {
        FeePaidResponse response = new FeePaidResponse();
        Reader query = new Reader();
        query.setJszh(request.getSzUserId());
        double payCount = 0.0;
        try {
            ReaderVo rv = readerDao.selectOne(query);

            List<CirculationLog> list = circulationLogDao.selectCirculationLogByJsrbh(rv.getJszh());
            if (list != null && list.size() > 0) {
                for (CirculationLog cl : list) {
                    int iRes = circulationLogDao.updateCirculationLog(rv.getJszh(), cl.getTsm(), Double.parseDouble(rv.getYqfk()));
                    if (iRes > 0) {
                        payCount += Double.parseDouble(rv.getYqfk());
                        response.addOK("将罚金成功");
                    } else {
                        response.addError("交罚金失败");
                        break;
                    }
                }
            } else {
                response.addError("无要交的罚金");
            }
            response.setPayCount(payCount);
            response.setOccurDate(DateFormat.dateToString(DateFormat.FORMATDATE));
        } catch (Exception ex) {
            ESERVICELOG.error(" payFee 异常： " + ex.getMessage());
            response.addError("交罚金异常");
        }
        return response;
    }

    @Override
    public String testSocket(String msg) {
        return null;
    }

	/****
	 * 解除标签绑定信息,该方法只对本地库进行操作
	 * @param request 请求参数
	 * @return 成功或失败的标签信息
	 * @date 2018年5月14日 下午3:08:53
	 */
	@Override
	public List<ItemResponse> doUntieLabels(LibraryRequest<String[]> request) {  
		List<ItemResponse> result = new ArrayList<ItemResponse>();
		ItemResponse item = null;
		for(String rfid : request.getData())
		{
			item = new ItemResponse();
			item.setRfid(rfid);
			SysBook b = sysBookDao.selectBookByRfid(rfid);
			if(b != null)
			{ 
				sysBookDao.deleteBookByRfid(rfid);
				item.setBookName(b.getBookname());
				item.addOK(rfid+"删除成功");
			}else 
				item.addError(rfid+"不存在"); 
			
			result.add(item);
		} 
		return result;
	}

	@Override
	public List<ItemResponse> doEdittingLabels(EditingRequest request,SysUser user) { 
	        List<ItemResponse> result = new ArrayList<ItemResponse>(); 
	        List<SysBook> uploadBooks = new ArrayList<SysBook>();
	        ItemResponse item = null; 
            for (SysBook book : request.getBooks()) {
                item = new ItemResponse(); 
                item.setRfid(book.getRfid());
            	SysBookVo sbook = sysBookDao.selectBookByRfid(book.getRfid());
                //已经存在的将不进行保存数据
                if (sbook == null) { 
                	sbook = new SysBookVo();
                	sbook.setRfid(book.getRfid());
                	sbook.setBarcode(book.getBarcode());
                	//查询图书其他信息
                	LibBookVo lbv = bookDao.getBookBytstm(book.getBarcode());
                	if(lbv != null)
                	{
                		//目前只使用了图书名称
                		sbook.setBookname(lbv.getZtm()); 
                	}
                    //todo
                	sbook.setCreate_by(user.getId());
                	sbook.setUpdate_by(user.getId());;
                    sysBookDao.insert(sbook); 
                } 
                item.setBarcode(sbook.getBarcode());
                item.setBookName(sbook.getBookname());
                uploadBooks.add(sbook); 
                item.addOK("上传数据成功");
                result.add(item); 
            } 
	        saveEditingLog(uploadBooks, user);
	        return result; 
	}  
	
    /**
     * 有问题 ！！！！！！！
     * 
     * @param books  采编成功图书信息
     * @param worker 采编人员
     */
    private void saveEditingLog(List<SysBook> books, SysUser worker) { 
        if (books != null && books.size() != 0) {
            for (SysBook book : books
                    ) {
                //保存日志
                EditingLog entity = new EditingLog();
                entity.setBook_id(book.getBarcode());
                entity.setRFID(book.getRfid()); 
                entity.setCreate_by(worker.getId());
                entity.setUpdate_by(worker.getId());
                editingLogDao.insert(entity);
            }
        }

    }

	@Override
	public String doTest(String id) { 
		
        EditingLog entity = new EditingLog();
        entity.setBook_id("test");
        entity.setRFID("test"); 
        entity.setCreate_by("test");
        entity.setUpdate_by("test");
        editingLogDao.insert(entity); 
		
	    CirculationLog cirLog = new CirculationLog(); 
	    cirLog.setCzy("test");
	    cirLog.setFlh("flh");
	    cirLog.setGcd("Gcd");
	    cirLog.setHsrq("hsrq");
	    cirLog.setId("id");
	    cirLog.setJg("jg"); 
        cirLog.setHsrq(DateFormat.dateToString(DateFormat.FORMATDATE));
        cirLog.setFj(0.00);
        circulationLogDao.insertCirculationLog(cirLog); 
		
		return "SUCCESS";
	}

	@Override
	public List<PatronResponse> doTransferReader(LibraryRequest<List<SysReader>> request) { 
		
		List<PatronResponse> result = new ArrayList<PatronResponse>(); 
		PatronResponse patron = null;
		for (SysReader reader : request.getData()) {
			patron = new PatronResponse();
			patron.setRfid(reader.getRfidCardNum());
			patron.setCampusCardNum(reader.getBarcode());
			//double 不能为null
			patron.setFeeMax(0.0);
			patron.setFine(0.0);
			patron.setReaderFee(0.0); 
			SysReader sr = sysReaderDao.selectReaderByRfid(reader.getRfidCardNum());
			if(sr != null)
			{
				//已经存在则提示
				patron.setStatus(0);
				patron.setReaderName(sr.getReaderName()); 
				patron.setMessage("用户已经存在"); 
				
			}else
			{
				Reader r = readerDao.selectById(reader.getBarcode());
				if(r == null)
				{
					//已经存在则提示
					patron.setStatus(0); 
					patron.setMessage(reader.getBarcode()+"用户不存在"); 
				}else
				{
					//借书证号与读者条码为同一个情况如果不同请修改
					reader.setCampusCardNum(reader.getBarcode());
					reader.setReaderName(r.getDzmc());
					reader.setCreate_by("");
					reader.setUpdate_by("");
					sysReaderDao.insert(reader);
					patron.setStatus(1); 
					patron.setMessage("成功");
					patron.setReaderName(reader.getReaderName());  
				} 
			}
			result.add(patron); 
		}
		return result;
	} 
	
	@Override
	public List<Tag> cBookStatus(RFIDRequest request) {
        List<Tag> list = new ArrayList<Tag>(); 
    	for (Tag tag : request.getTags()) {
    		SysBookVo sBook = sysBookDao.selectBookByRfid(tag.getEpc());
    		if(sBook != null)
    		{ 
	            Circulation circulation = circulationDao.getCirculationBytsm(sBook.getBarcode());
	            //没有借阅报警
	            if (circulation == null)
	            {
	            	list.add(tag); 
	            } 
	            if (ESERVICELOG.isDebugEnabled())
	                ESERVICELOG.debug("checkBookStatus circulation " + sBook.getBarcode() + "    " + (circulation == null ? "1" : "0")); 
    		}
        } 
        return list;
	}

}
